package CCRMServer;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import com.sun.rowset.CachedRowSetImpl;

import ocsf.server.*;
import Common.*;
import Common.Entities.*;
import CCRMServer.Controllers.*;

/**
 * This class handle any message received from CCRM clients
 * @author ori ziv
 * @author Oz Muktar
 *@author Ola
 */
public class CCRMServer extends AbstractServer {
	public static final int DEFAULT_PORT = 11170;							// server default listening port
	private static final int ArrayList = 0;
	public static ArrayList<String>usersList = new ArrayList<String>();		// logged-in users
	
	public CCRMServer (int port) {
		super(port);
	}
	
	public CCRMServer () {
		super(DEFAULT_PORT);
	}
	
	/**
	   * This method handles any messages received from the client.
	   *
	   * @param msg The message received from the client.
	   * @param client The connection from which the message originated.
	   */
	  public void handleMessageFromClient (Object msg, ConnectionToClient client) {
		  ServerRequest request = (ServerRequest)msg;
		  ServerAnswer answer = null;
		  
		  try {
			  switch (request.getCommand()) {
			  /**
			   * LOG_IN:
			   * This case handles user's login request
			   * It sends an Employee object with user's record of data in case of successful login
			   * or a relevant log-in failure message.
			   */
			  case LOG_IN:
				  Employee user = (Employee)request.getEntity();
				  // check if user is already logged-in
				  if (usersList.contains(user.getUserName())) {
					client.sendToClient(new ServerAnswer(SERVER_COMMANDS.LOG_IN, null, "User: " + user.getUserName() + " already logged in"));
				  } else {
					  // verify user name and password
					  user = UserVerify.registerUser(user.getUserName(), user.getPassword());
					  // DB connection exception
					  if (user == null)
						  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.LOG_IN, null, "DB Connection error"));
					  // bad password
					  else if (user.getUserName() != null && user.getID() == null)
						  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.LOG_IN, null, "Invalid password"));
					  // invalid user name
					  else if (user.getName() == null)
						  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.LOG_IN, null, "Invalid user name"));
					  // user's status is not active
					  else if (user.getStatus() == STATUS.NOT_ACTIVE || user.getStatus() == STATUS.SUSPENDED)
						  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.LOG_IN, null, "User can't login. Please contact your manager"));
					  // successfully logged-in
					  else {
						  usersList.add(user.getUserName());
						  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.LOG_IN, user, "Welcome to CCRM!"));
					  }
				  }
			  break;
			  /**
			   * LOG_OUT:
			   * This case handles user's log out request
			   * It removes user's user name from usersList and send acknowledge to the client
			   */
			  case LOG_OUT:
				  usersList.remove(usersList.indexOf((String)request.getUserID()));
				  client.sendToClient(new ServerAnswer(request.getCommand(), null));
				  break;
			  /**
			   * GET_CUSTOMER_BY_CONDITION:
			   * This case handles a request to search the DB according to a condition
			   * It sends an ArrayList of Customers with the search results (empty list if no results)
			   * Condition must be supplied in a correct SQL syntax!!!
			   * 
			   * @author ori ziv
			   */
			  case GET_CUSTOMER_BY_CONDITION:
				 ResultSet rs1=ServerCustomerManagement.searchCustomerbyCondition((String)request.getEntity());
				// System.out.println("rs.getEntity: " +  );
				 if(rs1==null)
					 client.sendToClient(new ServerAnswer(SERVER_COMMANDS.GET_CUSTOMER_BY_CONDITION, null, "DB Problem"));
					 
				 else
					 try {
						  CachedRowSetImpl crs = new CachedRowSetImpl();//
						  crs.populate(rs1);
						  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.GET_CUSTOMER_BY_CONDITION, crs, (String)request.getEntity()));
					  } catch (SQLException e) {
						  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.GET_CUSTOMER_BY_CONDITION, null, "DB Problem"));
					  }
				  
				  break;
			  /**
			   *This case handles a request to add customer to the db.
			   *It sends the client true for success or false for failure
			   *@author Oz Muktar
			   */
			  case ADD_CUSTOMER:
				  client.sendToClient(ServerCustomerManagement.addCustomer((Customer)request.getEntity()));
				  break;
			  /**
			   * UPDATE_CUSTOMER:
			   * This case handles a request to update an existing customer record in the db.
			   * It sends the client true for success or false for failure
			   * 
			   * @author ori ziv
			   */
			  case UPDATE_CUSTOMER:
				  client.sendToClient(ServerCustomerManagement.updateCustomerDetails((Customer)request.getEntity()));
				  break;
				  /**
				   * UPDATE_CUSTOMER_STATUS
				   * This case handles a request to update status of existing customer
				   * it sends to client true or false
				   */
			  case UPDATE_CUSTOMER_STATUS:
				  client.sendToClient(ServerCustomerManagement.updateCustomerStatus((String)request.getEntity()));
				  break;
				  /**
				   * ADD_PERMISSION
				   * This case handles a request to adding a new permission to the customer record in the db.
				   * @author Ola
				   */
			  case ADD_PERMISSION:
				  client.sendToClient(ServerCustomerManagement.registerPermission((Permission)request.getEntity()));
				  break;
				  /**
				   * GET_REGIONS:
				   * this case handles a result of search  region from DB.
				   */
			  case GET_REGIONS:
				  client.sendToClient(ServerCustomerManagement.searchRegion(request.getCondition()));
				  break;
				/**ADD_REGION:
				 * this case handles a request to adding a new region to the regions table in DB.
				 * @author Ola  
				 */
			  case ADD_REGION:
				  client.sendToClient(ServerCustomerManagement.addRegion((Regions)request.getEntity()));
			  break;
			  /**
			   * ADD_CATEGORY:
			   * This case handles add products category request
			   * It sends a message to the client (error or success)
			   */
			  case ADD_CATEGORY:
				  answer = CatalogServerManager.registerCategory((Category)request.getEntity());
				  if (answer == null)
					  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.ADD_CATEGORY, null, "Category already exists"));
				  else if (answer.getMessage().equals("DB Problem"))
					  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.ADD_CATEGORY, null, "DB Problem"));
				  else
					  client.sendToClient(answer);
				  break;
			  /**
			   * GET_CATEGORY_TYPES:
			   * This case handles a request to search all types related to a product's category
			   * It sends a ResultSet to the client with the search results
			   */
			  case GET_CATEGORY_TYPES:
				  Category cat = (Category)request.getEntity();
				  ResultSet rs = CatalogServerManager.searchCategoryByName(cat.getItmName());
				  
				  if (rs == null)
					  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.GET_CATEGORY_TYPES, null, "DB Problem"));
				  else
					try {
						if (!rs.next()) {
							client.sendToClient(new ServerAnswer(SERVER_COMMANDS.GET_CATEGORY_TYPES, null, "Category does not exsits"));
						  } else {
							  rs = CatalogServerManager.getCategoryTypes(cat.getItmName());
							  if (rs == null)
								  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.GET_CATEGORY_TYPES, null, "DB Problem"));
							  else {
								  CachedRowSetImpl crs = new CachedRowSetImpl();
								  crs.populate(rs);
								  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.GET_CATEGORY_TYPES, crs, cat.getItmName()));
							  }
						  }
					} catch (SQLException e) {
						client.sendToClient(new ServerAnswer(SERVER_COMMANDS.GET_CATEGORY_TYPES, null, "DB Problem"));
					}
				  rs = null;
				  break; 
			  /**
			   * ADD_TYPE:
			   * This case handles a request to add a new type to an existing product's category
			   * It sends a ResultSet to the client with the search results
			   */
			  case ADD_TYPE:
				  Type typ = (Type)request.getEntity();
				  rs = CatalogServerManager.searchCategoryByName(typ.getCategoryName());
				  if (rs == null)
					  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.ADD_TYPE, null, "DB Problem"));
				  else {
					  client.sendToClient(CatalogServerManager.registerType(typ.getItmName(), typ.getCategoryName()));
				  }
				  break;
			  /**
			   * This case handles a request to add new sale to the DB.
			   * It sends a boolean foe success or failure. 
			   */
			  case ADD_SALE:
				  answer = ServerSaleMangement.addSale((Sale)request.getEntity());
				  client.sendToClient(answer);
				  break;
			  /**
			   * ADD_TEMPLATE:
			   * This case handles a request to add a new Template to the DB
			   * It sends a ResultSet to the client with the search results
			   * 
			   * @author AL
			   */
			  case ADD_TEMPLATE:
				  answer = TemplateServerManager.AddTemplate((MarketingTemplate)request.getEntity());
					  client.sendToClient(answer);
				  break;
			  case SEARCH_TEMPLATE:
				  answer = TemplateServerManager.searchTemplateByID((MarketingTemplate)request.getEntity());
					  client.sendToClient(answer);
				  break;
			  /*case SHOW_SALESMEN_AND_CUSTOMERS:
				  client.sendToClient(ServerEmployeeManager.showSalesmenAndCustomers((Sale)(request.getEntity())));
				  break;*/
			  case ADD_PRODUCT:
				  client.sendToClient(CatalogServerManager.registerProduct(request.getCommand(), (Product)request.getEntity()));
				  break;
			  case SEARCH_PRODUCT:
				  rs = CatalogServerManager.searchProductByString((String)request.getEntity());
				  if (rs == null)
					  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.SEARCH_PRODUCT, null, "DB Problem"));
				  else {
					  try {
						  CachedRowSetImpl crs = new CachedRowSetImpl();
						  crs.populate(rs);
						  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.SEARCH_PRODUCT, crs, (String)request.getEntity()));
					  } catch (SQLException e) {
						  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.SEARCH_PRODUCT, null, "DB Problem"));
					  }
				  }
				  break;
			  case VIEW_TEMPLATE:
				  answer = TemplateServerManager.ViewTemplateByID((MarketingTemplate)request.getEntity());
					  client.sendToClient(answer);
				  break;
			  case UPDATE_TEMPLATE:
				  answer = TemplateServerManager.UpdateTemplate((MarketingTemplate)request.getEntity());
					  client.sendToClient(answer);
				  break;
			  case GET_PRODUCT:
				  client.sendToClient(CatalogServerManager.getProductByID((Long)request.getEntity()));
				  break;
			  case GET_PRODUCT_UPDATE:
				  answer = CatalogServerManager.getProductByID(new Long((String)request.getEntity()));
				  if (answer.getMessage().equals("Product does not exsits in the DB") || answer.getMessage().equals("DB Problem"))
					  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.GET_PRODUCT_UPDATE, null, answer.getMessage()));
				  else {
					  Object [] updateData = new Object[2];
					  updateData[0] = answer.getAnswer();
					  updateData[1] = CatalogServerManager.getAvailableTypes(((Product) updateData[0]).getProductCategoriesAndTypes(), (String)request.getEntity());
					  if (updateData[1] == null)
						  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.GET_PRODUCT_UPDATE, null, "DB Problem"));
					  else
						  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.GET_PRODUCT_UPDATE, updateData, ""));
				  }
				  break;

			  case UPDATE_PRODUCT_STATUS:
				  Object[] statusUpdate = (Object[]) request.getEntity();
				  long productID = (Long)statusUpdate[0];
				  STATUS newStatus = (STATUS)statusUpdate[1];
//				  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.UPDATE_PRODUCT_STATUS, null, CatalogServerManager.enableDisableProduct(productID, newStatus)));
				  break;
			  case UPDATE_PRODUCT:
				  client.sendToClient(CatalogServerManager.registerProduct(request.getCommand(), (Product)request.getEntity()));
				  break;

			  case VIEW_SALES_FOR_SALESMAN:
				  client.sendToClient(ServerSaleMangement.showSalesForSalesman((String)request.getEntity()));
				  break;
				  
			  case SEARCH_TEMPLATE_BY_STATUS:
				  rs = TemplateServerManager.SearchTemplateByStatus((String)request.getEntity());
				  if (rs == null)
					  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.SEARCH_TEMPLATE_BY_STATUS, null, "DB Problem"));
				  else {
					  try {
						  CachedRowSetImpl crs = new CachedRowSetImpl();
						  crs.populate(rs);
						  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.SEARCH_TEMPLATE_BY_STATUS, crs, (String)request.getEntity()));
					  } catch (SQLException e) {
						  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.SEARCH_TEMPLATE_BY_STATUS, null, "DB Problem"));
					  }
				  }
				  break;
			  case CUSTOMERS_REPORT:
				  client.sendToClient(ServerReportsManager.generateCustomersReport());
				  break;
			  case SALES_REPORT:
				  ArrayList<ResultSet> myrs = ServerReportsManager.generateSalesReport((String)request.getEntity());
				  if (myrs == null)
					  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.SALES_REPORT, null, "DB Problem"));
				  else {
					  ResultSet statistics = myrs.get(0);
					  ResultSet comments = myrs.get(1);
					  try {
						  CachedRowSetImpl cStatistics = new CachedRowSetImpl();
						  cStatistics.populate(statistics);
						  CachedRowSetImpl cComments = new CachedRowSetImpl();
						  cComments.populate(comments);
						  ArrayList<CachedRowSetImpl> mycrs = new ArrayList<CachedRowSetImpl>();
						  mycrs.add(cStatistics);
						  mycrs.add(cComments);
						  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.SALES_REPORT, mycrs, (String)request.getEntity()));
					  } catch (SQLException e) {
						  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.SALES_REPORT, null, "DB Problem"));
					  }
				  }
			  

				  break;
			  case SHOW_SALE_DETAILS:
				  client.sendToClient(ServerSaleMangement.getSaleDetails((Integer)request.getEntity()));
				  break;
			  case SHOW_CUSTOMERS_FOR_SALESMAN:
				  client.sendToClient(ServerCustomerManagement.showCustomersForSalesmanInSale((String[])request.getEntity()));
				  
				  break;

			  case ADDRESS_CUSTOMER:
				  client.sendToClient(ServerSaleMangement.addressCustomer((String[]) request.getEntity()));
				  break;
			  case SEARCH_CUST_RATES:
				  ArrayList<String[]> custRateSR = TemplateServerManager.SearchCustRates((Integer[])request.getEntity());
				  if (custRateSR == null)
					  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.SEARCH_CUST_RATES, null, "DB Problem"));
				  else {
					  Integer data[] = (Integer[])request.getEntity();
					  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.SEARCH_CUST_RATES, custRateSR, data[1].toString()));
				  }
				  break;
			  case ASSIGN_CUSTOMERS_TO_TEMPLATE:
				  client.sendToClient(TemplateServerManager.AssignCustomerToTemplate((ArrayList<CustomersInTemplate>)request.getEntity()));
				  break;
			  case ADD_RESPONSE:
				  client.sendToClient(ServerResponsesManagement.addResponse((CustomerResponse)request.getEntity()));
				  
				  break;
			  case SHOW_PRODUCT_IN_SALE:
				  client.sendToClient(CatalogServerManager.showProductInSale((CustomerResponse)request.getEntity()));
                  break;
			
			  case GET_APPROVED_TEMPLATES:
				  ResultSet approved = TemplateServerManager.SearchTemplateByStatus("approved");
				  if (approved == null)
					  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.GET_APPROVED_TEMPLATES, null, "DB Problem"));
				  else {
					  try {
						  CachedRowSetImpl cApproved = new CachedRowSetImpl();
						  cApproved.populate(approved);
						  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.GET_APPROVED_TEMPLATES, cApproved, ""));
					  } catch (SQLException e) {
						  client.sendToClient(new ServerAnswer(SERVER_COMMANDS.GET_APPROVED_TEMPLATES, null, "DB Problem"));
					  }
				  }
				  break;
			  }	  

		  	} catch (IOException e) {
			  System.out.println("Connection with client: " + client.getInetAddress().toString() + " has been lost");
		  	}
		  
	  }
}
